/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


/*************************************************************************
 * File: exdata_wrapper.h
 *************************************************************************
 *\author: starlove
 *************************************************************************/

#ifndef __MLSE_CODEC_EXDATA_WRAPPER_H__
#define __MLSE_CODEC_EXDATA_WRAPPER_H__

#include <codec/codec.h>
#include <platform/buffer.h>
#include <typeinfo>
#include <iostream>
#include <sstream>

template <typename T>
DATA_TP GetDataType()
{
    if(typeid(T) == typeid(char)) return DTP_INT;
    if(typeid(T) == typeid(short)) return DTP_INT;
    if(typeid(T) == typeid(int)) return DTP_INT;
    if(typeid(T) == typeid(INT64)) return DTP_INT64;
    if(typeid(T) == typeid(float)) return DTP_FLOAT;
    if(typeid(T) == typeid(bool)) return DTP_BOOL;
    if(typeid(T) == typeid(double)) return DTP_DOUBLE;
    if(typeid(T) == typeid(ENCODESTR)) return DTP_STR;
    if(typeid(T) == typeid(CMapData)) return DTP_MAP;
    if(typeid(T) == typeid(CListData)) return DTP_LIST;
    if(typeid(T) == typeid(BUFFER_WRAPPER)) return DTP_BUFFER;
    if(typeid(T) == typeid(LPBUFFER_WRAPPER)) return DTP_PBUFFER;

    return DTP_NULL;
};

inline unsigned int GetDataTypeSize(char tp)
{
	switch (tp)
	{
	case DTP_INT:
		return sizeof(int);
	case DTP_INT64:
		return sizeof(INT64);
	case DTP_FLOAT:
		return sizeof(float);
	case DTP_BOOL:
		return sizeof(bool);
	case DTP_DOUBLE:
		return sizeof(double);
	case DTP_STR:
		return sizeof(char *);
	default:
		return sizeof(void *);
	}
};

class CMapWrapper
{
public:
    CMapWrapper();
    CMapWrapper(bool);

    template <typename TK, typename T>
    bool Set(TK k, T v)
    {
        TK key = k;
        T val = v;
        DATA_TP ktp = GetDataType<TK>();
        DATA_TP tp = GetDataType<T>();
        return Add(&key, sizeof(key), &val, sizeof(val), ktp, tp);
    }

    void Reset();
    LPBUFFER_WRAPPER GetBuffer();

protected:
    bool Add(const void *pKey, unsigned int nKeySize, const void *pValue, unsigned int nSize, DATA_TP ktp, DATA_TP tp);

private:
    LPWRAPPER_DATA_HEADER m_header;
    BUFFER_WRAPPER m_buffer;
    CAutoExpandBuffer<4096> m_tmpbuffer;
};

class CListWrapper
{
public:
    CListWrapper();
    template <typename T>
    bool Add(T v)
    {
        T val = v;
        DATA_TP tp = GetDataType<T>();
        return Add(&val, sizeof(val), tp);
    }

    void Reset();
    LPBUFFER_WRAPPER GetBuffer();

protected:
    bool Add(const void *pValue, unsigned int nSize, DATA_TP tp);

private:
    LPWRAPPER_DATA_HEADER m_header;
    BUFFER_WRAPPER m_buffer;
    CAutoExpandBuffer<4096> m_tmpbuffer;
};
#endif
